package com.hejia.bulbul.controller;

import com.hejia.alauda.entity.*;
import com.hejia.alauda.service.BalanceAndFinancingService;
import com.hejia.alauda.service.ProductService;
import com.hejia.alauda.utils.HttpResponse;
import com.hejia.alauda.utils.Pager;
import com.hejia.alauda.utils.PagerHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("financialassets")
public class FinancialAssetController {

	private static final Log Logger = LogFactory
			.getLog(FinancialAssetController.class);

	@Resource
	private BalanceAndFinancingService financialAssetService;

	@Resource
	private BalanceAndFinancingService financialAssetStockEntryService;

	@Resource
	private ProductService productService;
	
	@Resource 
	private BalanceAndFinancingService financialAssetStockService;

    @Resource
    private ProductService templateService;

    @Resource
    private ProductService productTypeService;

	@RequestMapping("{financialAssetId}/products/{productId}")
	public String financialassetProduct(
			@PathVariable Long financialAssetId,
			@PathVariable Long productId,
			ModelMap model) {
		
		Product product = this.productService.getProductById(productId);
		List<ProductSettlementDate> productSettlementDates = this.financialAssetService
				.findProductSettlementDatesByProductId(productId);
		
		model.put("product", product);
		model.put("productSettlementDates", productSettlementDates);
		
		return "financialasset/productdetail";
	}

	@RequestMapping("{id}/products")
	public String products(@PathVariable Long id, ModelMap model) {

		FinancialAsset financialAsset = this.financialAssetService
				.findFinancialAssetById(id);
		List<Product> products = this.productService
				.findProductsByFinancialAssetId(id);
		List<FinancialAssetStockEntry> financialAssetStockEntries = financialAssetStockEntryService
				.findEntriesByFinancialAssetId(financialAsset.getId());
		List<ProductSettlementDate> productSettlementDates = this.financialAssetService
				.findProductSettlementDatesByFinancialAssetId(id);

		List<FinancialAssetProduct> financialAssetProducts = new ArrayList<>();
		for(Product product : products){
			FinancialAssetProduct financialAssetProduct = new FinancialAssetProduct(
					product, productSettlementDates, financialAssetStockEntries);
			financialAssetProducts.add(financialAssetProduct);
		}
		
		List<FinancialAssetStockEntry> FinancialAssetStockEntries = this.financialAssetStockEntryService
				.findStockEntriesByFinancialAssetId(id);
		BigDecimal inStockAmount = countInOutStocks(FinancialAssetStockEntries,
				FinancialAssetStockEntry.Type.In);
		BigDecimal outStockAmount = countInOutStocks(
				FinancialAssetStockEntries, FinancialAssetStockEntry.Type.Out);
		BigDecimal entryCalculateInventory = inStockAmount.subtract(outStockAmount);
		BigDecimal calculateInventory = this.financialAssetStockService.calculateFinancialAssetStock(id, new Date());
		
		model.put("financialAsset", financialAsset);
		model.put("financialAssetProducts", financialAssetProducts);
		model.put("entryCalculateInventory", entryCalculateInventory);
		model.put("calculateInventory", calculateInventory);

		return "financialasset/products";
	}

	@RequestMapping("{id}/inoutstockdetail")
	public String inOutStockDetail(@PathVariable Long id, ModelMap model) {

		FinancialAsset financialAsset = this.financialAssetService
				.findFinancialAssetById(id);
		List<FinancialAssetStockEntry> FinancialAssetStockEntries = this.financialAssetStockEntryService
				.findStockEntriesByFinancialAssetId(id);
		BigDecimal inStockAmount = countInOutStocks(FinancialAssetStockEntries,
				FinancialAssetStockEntry.Type.In);
		BigDecimal outStockAmount = countInOutStocks(
				FinancialAssetStockEntries, FinancialAssetStockEntry.Type.Out);
		BigDecimal entryCalculateInventory = inStockAmount.subtract(outStockAmount);
		
		BigDecimal calculateInventory = this.financialAssetStockService.calculateFinancialAssetStock(id, new Date());
		
		model.put("calculateInventory", calculateInventory);
		model.put("inStockAmount", inStockAmount);
		model.put("outStockAmount", outStockAmount);
		model.put("entryCalculateInventory", entryCalculateInventory);
		model.put("financialAsset", financialAsset);
		model.put("financialAssetStockEntries", FinancialAssetStockEntries);

		return "financialasset/inoutstockdetail";
	}

	/**
	 * 统计出入库总额
	 * 
	 * @param financialAssetStockEntries
	 * @param type
	 *            类型
	 * @return 出入库总额
	 */
	private BigDecimal countInOutStocks(
			List<FinancialAssetStockEntry> financialAssetStockEntries,
			FinancialAssetStockEntry.Type type) {
		BigDecimal amount = BigDecimal.ZERO;
		for (FinancialAssetStockEntry entry : financialAssetStockEntries) {
			if (entry.getType() == type) {
				amount = amount.add(entry.getAmount());
			}
		}
		return amount;
	}

	@RequestMapping(value = "{id}/delete", method = RequestMethod.POST)
	@ResponseBody
	public HttpResponse delete(@PathVariable Long id, ModelMap model) {

		HttpResponse response = new HttpResponse();

		try {
			this.financialAssetService.deleteFinancialAssetById(id);
			response.setCode("201");
			response.setStatus("success");
			response.setMessage("删除金融资产成功");
			response.setData(id);
		} catch (Exception e) {
			response.setCode("400");
			response.setStatus("error");
			response.setMessage("删除金融资产失败 " + e.getMessage());
			response.setData(id);
		}

		return response;
	}

	@RequestMapping("{id}/edit")
	public String edit(@PathVariable Long id, ModelMap model) {

		FinancialAsset financialAsset = this.financialAssetService
				.findFinancialAssetById(id);
        List<Template> list = templateService.getAllTemplates();
        model.addAttribute("list", list);
    		model.put("financialAsset", financialAsset);

		return "financialasset/edit";
	}

	@RequestMapping(value = "{id}", method = RequestMethod.POST)
	public String edit(FinancialAsset financialAsset, ModelMap model) {
		try {
			this.financialAssetService.updateFinancialAsset(financialAsset);
			return "redirect:/financialassets";
		} catch (Exception e) {
			Logger.error("更新金融资产失败", e);
			model.put("error", "更新金融资产失败 " + e.getMessage());
			model.put("financialAsset", financialAsset);
			return "financialasset/edit";
		}
	}

	@RequestMapping("add")
	public String add(Model model) {
        List<Template> list = templateService.getAllTemplates();
        model.addAttribute("list", list);
		return "financialasset/add";
	}

	@RequestMapping(method = RequestMethod.POST)
	public String add(FinancialAsset financialAsset, ModelMap model) {
		try {

			if (financialAsset.getDueDate().getTime() <= financialAsset
					.getValueDate().getTime()) {
				model.put("error", "到期日必须大于起息日");
				model.put("financialAsset", financialAsset);
				return "financialasset/add";
			} else {
				this.financialAssetService.addFinancialAsset(financialAsset);
				return "redirect:/financialassets";
			}
		} catch (Exception e) {
			Logger.error("添加金融资产失败", e);
			model.put("error", "添加金融资产失败 " + e.getMessage());
			model.put("financialAsset", financialAsset);
			return "financialasset/add";
		}
	}

	@RequestMapping
	public String list(String keyword, Date valueDateStart, Date valueDateEnd,
			Date dueDateStart, Date dueDateEnd, Pager<FinancialAsset> pager,
			ModelMap model) {

		pager = financialAssetService.findFinancialAssets(keyword,
				valueDateStart, valueDateEnd, dueDateStart, dueDateEnd, pager);

		DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		PagerHelper<FinancialAsset> helper = new PagerHelper<>();
		helper.setPager(pager);
		Map<String, String> map = new HashMap<>();
		if (keyword != null) {
			map.put("keyword", keyword);
		}
		if (valueDateStart != null) {
			map.put("valueDateStart", format.format(valueDateStart));
		}
		if (valueDateEnd != null) {
			map.put("valueDateEnd", format.format(valueDateEnd));
		}
		if (dueDateStart != null) {
			map.put("dueDateStart", format.format(dueDateStart));
		}
		if (dueDateEnd != null) {
			map.put("dueDateEnd", format.format(dueDateEnd));
		}
		helper.setParams(map);
		helper.setBaseUrl("/financialassets");

		model.put("pagerHelper", helper);
		model.put("keyword", keyword);
		model.put("valueDateStart", valueDateStart);
		model.put("valueDateEnd", valueDateEnd);
		model.put("dueDateStart", dueDateStart);
		model.put("dueDateEnd", dueDateEnd);
		model.put("financialassets", pager);

		return "financialasset/list";
	}

	@InitBinder
	public void initBinder(WebDataBinder binder) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		dateFormat.setLenient(false);
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				dateFormat, true));
	}

	/**
	 * 金融资产产品
	 * 
	 * @author hyr
	 *
	 */
	public class FinancialAssetProduct {

		private Product product; // 产品
		private List<ProductSettlementDate> productSettlementDates; // 产品结息日
		private List<FinancialAssetStockEntry> financialAssetStockEntries; // 产品出入库记录
		
		public FinancialAssetProduct(Product product, 
				List<ProductSettlementDate> productSettlementDates, 
				List<FinancialAssetStockEntry> financialAssetStockEntries){
			
			this.product = product;
			this.productSettlementDates = new ArrayList<>();
			this.financialAssetStockEntries = new ArrayList<>();
			
			for(ProductSettlementDate productSettlementDate : productSettlementDates){
				if(productSettlementDate.getProductId().equals(this.product.getId())){
					this.productSettlementDates.add(productSettlementDate);
				}
			}
			
			for(FinancialAssetStockEntry entry : financialAssetStockEntries){
				if(entry.getProduct() != null && 
				   entry.getProduct().getId().equals(this.product.getId())){
					this.financialAssetStockEntries.add(entry);
				}
			}
		}

		public Product getProduct() {
			return product;
		}

		public void setProduct(Product product) {
			this.product = product;
		}

		public List<ProductSettlementDate> getProductSettlementDates() {
			return productSettlementDates;
		}

		public void setProductSettlementDates(
				List<ProductSettlementDate> productSettlementDates) {
			this.productSettlementDates = productSettlementDates;
		}

		public List<FinancialAssetStockEntry> getFinancialAssetStockEntries() {
			return financialAssetStockEntries;
		}

		public void setFinancialAssetStockEntries(
				List<FinancialAssetStockEntry> financialAssetStockEntries) {
			this.financialAssetStockEntries = financialAssetStockEntries;
		}
		
		/**
		 * 是否有未售金额未入库
		 * @return true - 是，false - 否
		 */
		public Boolean getIsNotSoldNotInStock(){
			
			if(!(this.product.getTag().equals(3) ||
			   this.product.getTag().equals(4))){
				return false;
			}
			
			if(this.getProduct().getSoldAmount().compareTo(this.getProduct().getTotalAmount()) >= 0){
				return false;
			}
			
			for(FinancialAssetStockEntry entry : financialAssetStockEntries){
				if(entry.getPurpose().equals(FinancialAssetStockEntry.Purpose.SoldInStock) &&
				   entry.getProduct().getId().equals(this.product.getId())){
					return false;
				}
			}
			
			return true;
		}
		
		/**
		 * 是否超卖未出库
		 * @return
		 */
		public Boolean getIsOversellNotOutStock(){
			
			if(!(this.product.getTag().equals(3) ||
			     this.product.getTag().equals(4))){
				return false;
			}
			
			if(this.getProduct().getSoldAmount().compareTo(this.getProduct().getTotalAmount()) <= 0){
				return false;
			}
			
			for(FinancialAssetStockEntry entry : financialAssetStockEntries){
				if(entry.getPurpose().equals(FinancialAssetStockEntry.Purpose.Oversell) &&
				   entry.getProduct().getId().equals(this.product.getId())){
					return false;
				}
			}
			
			return true;
		}
		
		/**
		 * 是否用户回款未入库
		 * @return true - 是，false - 否
		 */
		public Boolean getIsPaymentCollectionNotInStock(){
			
			if(this.productSettlementDates.size() < 1){
				return false;
			}
			
			// 是否有未入库记录
			Date now = new DateTime().toLocalDate().toDate();
			for(ProductSettlementDate productSettlementDate: productSettlementDates){
				
				// 是否到达结息日
				if(now.compareTo(productSettlementDate.getSettlementDate()) < 0){
					continue;
				}
				
				// 是否已回款入库
				Boolean isInStock = false;
				for(FinancialAssetStockEntry entry : financialAssetStockEntries){
					if(entry.getPurpose().equals(FinancialAssetStockEntry.Purpose.PaymentCollection)){
						DateTime settlementDate = new DateTime(productSettlementDate.getSettlementDate().getTime());
						DateTime postingDate = new DateTime(entry.getPostingDate());
						if(settlementDate.toLocalDate().equals(postingDate.toLocalDate())){
							isInStock = true;
						}
					}
				}
				
				if(!isInStock){
					return true;
				}
			}
			
			return false;
		}
	}
}
